package com.mzba.place.utils;

import java.io.BufferedReader;
import java.io.Closeable;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HTTP;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;

import android.content.Context;
import android.os.AsyncTask;
import android.os.Handler;
import android.util.Log;

import com.mzba.place.utils.CustomMultiPartEntity.ProgressListener;
/**
 * 提交数据
 * @author 06peng
 *
 */
public class UploadFileUtil extends AsyncTask<String, Integer, Integer> {
	
	private static final String tag = UploadFileUtil.class.getSimpleName();
	
	private Context context;
	private Handler handler;
	private HashMap<String, File> filesMap;
	private HashMap<String, String> paramsMap;
	private long totalSize;
	private String url;
	
	
	public UploadFileUtil(Context context, Handler handler, String url, HashMap<String, String> paramsMap) {
		this.context = context;
		this.handler = handler;
		this.url = url;
		this.paramsMap = paramsMap;
	}

	/**
	 * 
	 * @param context
	 * @param handler
	 * @param url
	 * @param paramsMap
	 * @param filesMap String的格式应该是“xxx.png”
	 */
	public UploadFileUtil(Context context, Handler handler, String url, HashMap<String, String> paramsMap, HashMap<String, File> filesMap) {
		this.context = context;
		this.handler = handler;
		this.url = url;
		this.filesMap = filesMap;
		this.paramsMap = paramsMap;
	}
	
	
	@Override
	protected void onPreExecute() {
		super.onPreExecute();
		if (filesMap != null) {
			//TODO 如果文件不为空，显示文件上传的进度框
		} else {
			//TODO
		}
	}
	
	@Override
	protected void onPostExecute(Integer result) {
		super.onPostExecute(result);
		if (filesMap != null) {
			//TODO 如果文件不为空，隐藏文件上传的进度框
		} else {
			
		}
	}
	
	@Override
	protected void onProgressUpdate(Integer... values) {
		super.onProgressUpdate(values);
		//TODO show values[0] + "%"
	}
	
	@Override
	protected Integer doInBackground(String... arg0) {
		String result = null;
		try {
			if (filesMap != null) {
				result = submitFileByEntity();
			} else {
				result = doPost();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
	
	
	private String doPost() {
		BaseHttpClient client = BaseHttpClient.newInstance(context, tag);
		HttpPost request = null;
		InputStream entityStream = null;
		String result = null;
		try {
			request = new HttpPost(url);
			List<NameValuePair> params = new ArrayList<NameValuePair>();
			for (Map.Entry<String, String> m : paramsMap.entrySet()) {
				params.add(new BasicNameValuePair(m.getKey(), m.getValue()));
			}
			request.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));
			Log.d(tag, "request-url=" + url + (params != null ? params.toString() : null));
			HttpResponse response = client.execute(request);
			int statusCode = response.getStatusLine().getStatusCode();
			if (statusCode == 200) {
				entityStream = response.getEntity().getContent();
				result = convertStreamToString(entityStream);
			}
			Log.d(tag, "request-statusCode=" + statusCode);
		} catch (Exception e) {
			request.abort();
			e.printStackTrace();
			
		} finally {
			closeStream(entityStream);
			closeClient(client);
		}
		
		Log.d(tag, "result="+result);
		return result;
	}

	protected String submitFile() {
		String result = null;
		try {
			long length = 0;
			int progress;
			int bytesRead, bytesAvailable, bufferSize;
			long totalSize = 0;
			byte[] buffer;
			int maxBufferSize = 10 * 1024;// 10KB

			String BOUNDARY = java.util.UUID.randomUUID().toString();
			String PREFIX = "--", LINEND = "\r\n";
			String MULTIPART_FROM_DATA = "multipart/form-data";
			String CHARSET = "UTF-8";

			URL uri = new URL(url);
			HttpURLConnection conn = (HttpURLConnection) uri.openConnection();
			conn.setReadTimeout(60 * 1000); // 缓存的最长时间
			conn.setConnectTimeout(60 * 1000);
			conn.setDoInput(true);// 允许输入
			conn.setDoOutput(true);// 允许输出
			conn.setUseCaches(false); // 不允许使用缓存
			conn.setRequestMethod("POST");
			conn.setRequestProperty("connection", "keep-alive");
			conn.setRequestProperty("Charsert", "UTF-8");
			conn.setRequestProperty("Content-Type", MULTIPART_FROM_DATA + ";boundary=" + BOUNDARY);

			// 首先组拼文本类型的参数
			StringBuilder sb = new StringBuilder();
			for (Map.Entry<String, String> entry : paramsMap.entrySet()) {
				sb.append(PREFIX);
				sb.append(BOUNDARY);
				sb.append(LINEND);
				sb.append("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"" + LINEND);
				sb.append("Content-Type: text/plain; charset=" + CHARSET + LINEND);
				sb.append("Content-Transfer-Encoding: 8bit" + LINEND);
				sb.append(LINEND);
				sb.append(entry.getValue());
				sb.append(LINEND);
			}
			Log.i("httptest", "test" + sb.toString());
			DataOutputStream outStream = new DataOutputStream(conn.getOutputStream());
			outStream.write(sb.toString().getBytes());
			Log.i("httptest", "testend");
			InputStream in = null;
			// 发送文件数据
			if (filesMap != null) {
				for (Map.Entry<String, File> mFile : filesMap.entrySet()) {
					totalSize += mFile.getValue().length();
				}
				for (Map.Entry<String, File> mFile : filesMap.entrySet()) {
					StringBuilder sb1 = new StringBuilder();
					sb1.append(PREFIX);
					sb1.append(BOUNDARY);
					sb1.append(LINEND);
					sb1.append("Content-Disposition: form-data; name=\"pic\"; filename=\"" + mFile.getKey() + "\"" + LINEND);
					sb1.append("Content-Type: image/jpeg; charset=" + CHARSET + LINEND);
					sb1.append(LINEND);
					outStream.write(sb1.toString().getBytes());
					
					FileInputStream fileInputStream = new FileInputStream(mFile.getValue());  
	                bytesAvailable = fileInputStream.available();  
	                bufferSize = Math.min(bytesAvailable, maxBufferSize);//设置每次写入的大小  
	                buffer = new byte[bufferSize];  
	                bytesRead = fileInputStream.read(buffer, 0, bufferSize);  
	                while (bytesRead > 0) {  
	                	outStream.write(buffer, 0, bufferSize);  
	                    length += bufferSize;  
	                    Thread.sleep(500);  
	                    progress = (int) ((length * 100) / totalSize);  
	                    publishProgress(progress,(int)length);  
	  
	                    bytesAvailable = fileInputStream.available();  
	                    bufferSize = Math.min(bytesAvailable, maxBufferSize);  
	                    bytesRead = fileInputStream.read(buffer, 0, bufferSize);  
	                }  
	                fileInputStream.close();
					outStream.write(LINEND.getBytes());
					Log.i("httptest:pic", "test" + sb1.toString());
				}

				// 请求结束标志
				byte[] end_data = (PREFIX + BOUNDARY + PREFIX + LINEND).getBytes();
				outStream.write(end_data);
				outStream.flush();
				publishProgress(100,(int)length);
			}

			// 得到响应码
			int res = conn.getResponseCode();
			Log.i(tag, res + "-----------------");
			if (res == 200) {
				in = conn.getInputStream();
				result = HttpUtils.convertStreamToString(in);
			}
			outStream.close();
			conn.disconnect();
			Log.d(tag, "result=" + result);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}
	
	private String submitFileByEntity() {
		String serverResponse = null;
		try {
			HttpClient httpClient = new DefaultHttpClient();
			HttpContext httpContext = new BasicHttpContext();
			HttpPost httpPost = new HttpPost(url);
			CustomMultiPartEntity multipartContent = new CustomMultiPartEntity(
				new ProgressListener() {
					@Override
					public void transferred(long num) {
						publishProgress((int) ((num / (float) totalSize) * 100));
					}
				});

			// We use FileBody to transfer an image
			for (Map.Entry<String, String> entry : paramsMap.entrySet()) {
				multipartContent.addPart(entry.getKey(), new StringBody(entry.getValue() == null ? "" : entry.getValue()));
			}
			for (Map.Entry<String, File> mFile : filesMap.entrySet()) {
				multipartContent.addPart(mFile.getKey(), new FileBody(mFile.getValue()));
			}
			totalSize = multipartContent.getContentLength();

			// Send it
			httpPost.setEntity(multipartContent);
			HttpResponse response = httpClient.execute(httpPost, httpContext);
			serverResponse = EntityUtils.toString(response.getEntity());
		} catch (Exception e) {
			e.printStackTrace();
		}
		return serverResponse;
	}

	static String convertStreamToString(InputStream is) {
		StringBuilder sb = new StringBuilder();
		try {
			BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"), 8 * 1024);
			String line = null;
			while ((line = reader.readLine()) != null) {
				sb.append(line);
			}
		} catch (IOException e) {
			sb.delete(0, sb.length());
		} finally {
			closeStream(is);
		}
		return sb.toString();
	}
	
	private static void closeStream(Closeable stream) {
		if (stream != null) {
			try {
				stream.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	private static void closeClient(BaseHttpClient client) {
		if (client != null) {
			client.close();
			client = null;
		}
	}
}
